﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;

namespace monitor_server
{
    public delegate void text_b(string a);
    public delegate void enabler(Control a, bool b);

    public partial class Form9 : Form
    {
        
        form9enable d;
        Socket soc;
        IPAddress ip;
        Timer tim;
        IPEndPoint ipe;
        ToolTip tip = new ToolTip();
        Keys key;
        bool tb1A = false;
        bool tb2A = false;
        string last_tb1;
        string last_tb2;
        bool receiving = false;
        string dev_name;
        byte[] get = new byte[] { 0x67, 0x65, 0x74 };       //Команда get
        byte[] rec = new byte[9];                           //Буфер приема/отправки параметров эталона и нормы
        public Form9(form9enable sender1, IPAddress sender2, string sender3)
        {
            InitializeComponent();
            d = sender1;                
            ip = sender2;
            dev_name = sender3;         //Имя измерителя
        }

        private void Form9_Load(object sender, EventArgs e)
        {
            tim = new Timer();
            tim.Interval = 3000;
            tim.Tick += new EventHandler(tim_Tick);            
            textBox1.Enabled = false;
            textBox2.Enabled = false;
            this.Text = "Изменение параметров измерителя";
            toolStripStatusLabel2.Text = dev_name + ":";
            toolStripStatusLabel1.Text = "Установка соединения...";
            soc = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            soc.ReceiveTimeout = 3000; //таймауты приёма и отправки
            soc.SendTimeout = 3000;
            int port = 25001;
            IPEndPoint lpe;            
            ipe = new IPEndPoint(ip, 25001);
            IPAddress lip = IPAddress.Any;
            while (true)
            {
                try
                {
                    lpe = new IPEndPoint(lip, port);
                    soc.Bind(lpe);
                    break;
                }
                catch (SocketException)
                {
                    port++;
                }
            }
            button1.Enabled = false;
            button2.Enabled = false;
            connect();
            
        }

        void connect()              //Попытка получения данных с измерителя
        {
            try
            {
                soc.EndSendTo(soc.BeginSendTo(get, 0, get.Length, SocketFlags.None, ipe, null, null));
                if (!receiving)
                    soc.BeginReceive(rec, 0, 9, SocketFlags.None, new AsyncCallback(tratata), soc);
                receiving = true;
                tim.Start();
            }
            catch (SocketException)
            {

                MessageBox.Show("Не удалось установить связь с устройством " + dev_name + ".");
                d(false);
                this.Close();
                return;
            }
            catch (ObjectDisposedException)
            {

            }
            
        }

        void tim_Tick(object sender, EventArgs e)           //Тик таймера (Связь с измерителем не установлена)
        {
            tim.Stop();
            DialogResult res;
            res = MessageBox.Show("Не удалось установить связь с устройством " + dev_name + ". Желаете повторить?", "", MessageBoxButtons.RetryCancel);
            if (res == DialogResult.Cancel)
            {
                receiving = false;
                soc.Shutdown(SocketShutdown.Both);
                soc.Close();
                d(false);
                this.Close();
                return;
            }
            else
            {
                button1.Enabled = false;
                connect();
            }
            
            
        }
        void tratata(IAsyncResult ar)                       //Обработка пришедшего пакета
        {            
            tim.Stop();
            Socket sock = (Socket)ar.AsyncState;
            int bytesRec;
            string str = "";
            text_b tb;
            tb = status_label_inv;
            try
            {
                bytesRec = sock.EndReceive(ar);
            }
            catch (Exception)
            {
                //str = "Произошла ошибка при попытке подключения.";                
                //tb(str);
                return;
            }
            str = rec[7].ToString() + "," + rec[8].ToString();
            tb = tb2_inv;
            try
            {
                textBox2.Invoke(tb, str);
            }
            catch (Exception)
            { }
            str = "";
            for (int i = 0; i < 7; i++)
            {
                str += rec[i].ToString();
            }
            tb = tb1_inv;
            textBox1.Invoke(tb, str);
            str = "Готово.";
            tb = status_label_inv;
            tb(str);
            soc.Shutdown(SocketShutdown.Both);
            soc.Close();
            enabler en = enabled_inv;
            button2.Invoke(en, button2, true);
            button1.Invoke(en, button1, true);
        }

        private void enabled_inv(Control a, bool b)
        {
            a.Enabled = b;
        }

        private void tb1_inv(string str)
        {
            textBox1.Text = str;
            last_tb1 = str;
            textBox1.Enabled = true;
            tb1A = true;
        }

        private void tb2_inv(string str)
        {
            textBox2.Text = str;
            last_tb2 = str;
            textBox2.Enabled = true;
            tb2A = true;
        }

        private void status_label_inv(string str)
        {
            try
            {
                toolStripStatusLabel1.Text = str;               //Win32Exception
            }
            catch (Win32Exception)
            { }
        }

        private void button1_Click(object sender, EventArgs e)          //Применить
        {
            button1.Enabled = false;
            byte[] send = new byte[9];
            soc = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            soc.ReceiveTimeout = 3000;
            IPEndPoint lpe;
            if (!soc.IsBound)                                           //Привязываем сокет, поиск свободного порта
            {
                IPAddress local_ip = IPAddress.Any;
                int port = 25001;
                while (true)
                {
                    try
                    {
                        lpe = new IPEndPoint(local_ip, port);
                        soc.Bind(lpe);
                        break;
                    }
                    catch (SocketException)
                    {
                        port++;
                    }
                }
            }
            //Формируем массив файт для отправки
            //Эталон
            if (textBox1.Text.Trim().Length < 7)
            {
                int l = 7 - textBox1.Text.Length;
                for (int i = 0; i < l; i++)
                {
                    textBox1.Text += "0";
                }
            }
            for (int i = 0; i < 7; i++)
            {
                send[i] = (byte)int.Parse(textBox1.Text.Substring(i, 1));
            }
            //Норма
            send[7] = (byte)int.Parse(textBox2.Text.Substring(0, 1));
            if (textBox2.Text.Length == 2)
                send[8] = (byte)int.Parse(textBox2.Text.Substring(1, 1));
            else
                send[8] = (byte)int.Parse(textBox2.Text.Substring(2, 1));
            //Отправка
            soc.SendTo(send, ipe);
            try
            {
                soc.Receive(send);
            }
            catch (SocketException)
            {
                MessageBox.Show("Устройство не ответило на зпрос.");
                d(false);
                this.Close();
                return;
            }
            if (send[0] == 'k')
                MessageBox.Show("Параметры успешно установлены.");
            else                
                MessageBox.Show("Неопределенный ответ с устройства.");
            d(false);
            this.Close();
            return;

        }

        private void button2_Click(object sender, EventArgs e)      //Отмена
        {
            tim.Stop();
            tim.Dispose();            
            d(false);
            this.Close();
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            if (!tb1A) return;
            tip.Hide(this);
            int ss;
            int pos = textBox1.SelectionStart;
            if (textBox1.Text.Length > 7)
            {
                textBox1.Text = last_tb1;
                textBox1.SelectionStart = pos;
                tip.Show("Количество элементов не должно превышать 7.", textBox1, 1000);
            }
            else if (!int.TryParse(textBox1.Text, out ss))
            {
                textBox1.Text = last_tb1;
                textBox1.SelectionStart = pos;
                tip.Show("Допускаются только цифры.", textBox1, 1000);
            }
            else
            {
                last_tb1 = textBox1.Text;
                button1.Enabled = true;
            }
        }

        private void textBox2_TextChanged(object sender, EventArgs e)
        {
            if (!tb2A) return;
            tip.Hide(this);
            button1.Enabled = false;
            bool comma;
            if (last_tb2.Contains(',') || last_tb2.Contains('.'))
                comma = true;
            else comma = false;
            int pos = textBox2.SelectionStart;
            int ss;
          if (textBox2.Text.Length > 3)
            {
                textBox2.Text = last_tb2;
                textBox2.SelectionStart = pos;
                tip.Show("Количество элементов не должно превышать 3.", textBox2, 1000);
            }
            //else if (key == Keys.Oemcomma || key == Keys.OemPeriod)
            else if (((key == Keys.Oemcomma || key == Keys.OemPeriod) && InputLanguage.CurrentInputLanguage.Culture.EnglishName.Contains("English"))
                || (((key.ToString() == "OemQuestion" || key.ToString() == "OemQuestion, Shift") && InputLanguage.CurrentInputLanguage.Culture.EnglishName.Contains("Russia")))
                || (key.ToString() == "Decimal"))
            {
                if (!comma)
                {
                    comma = true;
                    last_tb2 = textBox2.Text;
                }
                else
                {
                    textBox2.Text = last_tb2;
                    textBox2.SelectionStart = pos;
                }

            }
            else if (key == Keys.Back || key == Keys.Delete)
            {
                last_tb2 = textBox2.Text;
                if (!last_tb2.Contains(',') && !last_tb2.Contains('.'))
                    comma = false;
            }
            else if ((key < Keys.D0 || key > Keys.D9) && (key < Keys.NumPad0 || key > Keys.NumPad9))
            {
                textBox2.Text = last_tb2;
                textBox2.SelectionStart = pos;
                tip.Show("Допускаются только цифры.", textBox2, 1000);
            }
            else
            {
                last_tb2 = textBox2.Text;
            }
            if ((textBox2.Text.Length == 3
                    && int.TryParse(textBox2.Text.Substring(0, 1), out ss)
                    && int.TryParse(textBox2.Text.Substring(2, 1), out ss)
                    && (textBox2.Text[1] == ',' || textBox2.Text[1] == '.'))
                    || (textBox2.Text.Length == 2 && int.TryParse(textBox2.Text, out ss)))
                button1.Enabled = true;
                

        }

        private void textBox2_KeyDown(object sender, KeyEventArgs e)
        {
            key = e.KeyData;
        }
    }
}
